package com.daiyang.campus_lucky_draw.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.daiyang.campus_lucky_draw.common.enums.UserIdentityEnum;
import com.daiyang.campus_lucky_draw.common.error.ServiceErrorCodeConstants;
import com.daiyang.campus_lucky_draw.common.exception.ServiceException;
import com.daiyang.campus_lucky_draw.common.utils.JWTUtil;
import com.daiyang.campus_lucky_draw.common.utils.RegexUtil;
import com.daiyang.campus_lucky_draw.contreller.UserController;
import com.daiyang.campus_lucky_draw.contreller.param.ShortMessageLoginParam;
import com.daiyang.campus_lucky_draw.contreller.param.UserLoginParam;
import com.daiyang.campus_lucky_draw.contreller.param.UserPasswordLoginParam;
import com.daiyang.campus_lucky_draw.contreller.param.UserRegisterParam;
import com.daiyang.campus_lucky_draw.mapper.DO.UserDO;
import com.daiyang.campus_lucky_draw.mapper.UserMapper;
import com.daiyang.campus_lucky_draw.mapper.DO.Encrypt;
import com.daiyang.campus_lucky_draw.service.UserService;
import com.daiyang.campus_lucky_draw.service.VerificationCodeService;
import com.daiyang.campus_lucky_draw.service.dto.UserDTO;
import com.daiyang.campus_lucky_draw.service.dto.UserLoginDTO;
import com.daiyang.campus_lucky_draw.service.dto.UserRegisterDTO;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private VerificationCodeService verificationCodeService;
    @Override
    public UserRegisterDTO register(UserRegisterParam param) {
        // 参数校验
       checkRegisterInfo(param);
        //入库
        UserDO userDO = new UserDO();
        userDO.setUserName(param.getName());

        userDO.setEmail(param.getMail());
        userDO.setIdentity(param.getIdentity());
        if(StringUtils.hasText(param.getPassword())){
            userDO.setPassword(DigestUtil.sha256Hex(param.getPassword()));
        }
        userDO.setPhoneNumber(new Encrypt(param.getPhoneNumber()));
        userMapper.insert(userDO);



        //返回
        UserRegisterDTO userRegisterDTO = new UserRegisterDTO();
        userRegisterDTO.setUserId(userDO.getId());
        return userRegisterDTO;

    }

    @Override
    public UserLoginDTO login(UserLoginParam request) {
        UserLoginDTO userLoginDTO = null;
        if (request instanceof UserPasswordLoginParam loginParam) {
            userLoginDTO = loginByPassword(loginParam);
        } else if (request instanceof ShortMessageLoginParam loginParam) {
            userLoginDTO = loginByShortMessage(loginParam);
        } else {
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        }
        return userLoginDTO;
    }

    @Override
    public List<UserDTO> findUserList(UserIdentityEnum identity) {
        String identityString = null == identity ? null : identity.name();
        List<UserDO> userDOList = userMapper.selectUserList(identityString);
        return userDOList.stream()
                .map(userDO -> {
                    UserDTO userDTO = new UserDTO();
                    userDTO.setUserId(userDO.getId());
                    userDTO.setUserName(userDO.getUserName());
                    userDTO.setEmail(userDO.getEmail());
                    userDTO.setPhoneNumber(userDO.getPhoneNumber().getValue());

                    userDTO.setIdentity(UserIdentityEnum.fromName(userDO.getIdentity()));
                    return userDTO;
                }).collect(Collectors.toList());
    }

    private UserLoginDTO loginByShortMessage(ShortMessageLoginParam loginParam) {
        String loginMobile = loginParam.getLoginMobile();
        String verificationCode = loginParam.getVerificationCode();
        if (!RegexUtil.checkMobile(loginMobile)) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        // ⽤⼾查询
        UserDO userDO = userMapper.selectByPhoneNumber(
                new Encrypt(loginMobile));
        if (null == userDO) {
            throw new ServiceException(ServiceErrorCodeConstants.USER_NOT_EXIST);
        } else if (StringUtils.hasText(loginParam.getMandatoryIdentity())
                &&
                !loginParam.getMandatoryIdentity().equals(userDO.getIdentity())) {
            // 存在强制⾝份登录，但⾝份不相同
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }
        // 验证码校验
        String code = verificationCodeService.getVerificationCode(loginMobile);
        if (!StringUtils.hasText(code) || !code.equals(verificationCode)) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.VERIFICATION_CODE_ERROR);
        }
        // 返回token
        Map<String , Object> claims = new HashMap<>();
        claims.put("userId", userDO.getId());
        claims.put("identity", userDO.getIdentity());
        String token = JWTUtil.genJwt(claims);
        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.fromName(userDO.getIdentity()));
        return userLoginDTO;

    }

    private UserLoginDTO loginByPassword(UserPasswordLoginParam loginParam) {
        String loginName = loginParam.getLoginName();
        String password = loginParam.getPassword();
        UserDO userDO=null;
        if(!StringUtils.hasText(password)){
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }
        if(RegexUtil.checkMail(loginName)){
            //根据邮箱获取用户信息
            userDO=userMapper.selectByEmail(loginName);
        } else if(RegexUtil.checkMobile(loginName)){
            //根据⼿机号获取用户信息
            userDO=userMapper.selectByPhoneNumber(new Encrypt(loginName));
        } else {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_OR_PHONE_ERROR);
        }
        if(userDO==null){
            new ServiceException(ServiceErrorCodeConstants.USER_NOT_EXIST);
        } else if((StringUtils.hasText(loginParam.getMandatoryIdentity()))
                && !loginParam.getMandatoryIdentity().equals(userDO.getIdentity())) {
            // 存在强制⾝份登录，但⾝份不相同
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        } else if (!userDO.getPassword().equals(
                DigestUtil.sha256Hex(password))) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }
        // 获取到⽤⼾信息且密码正确，返回token
        Map<String , Object> claims = new HashMap<>();
        claims.put("userId", userDO.getId());
        claims.put("identity", userDO.getIdentity());
        String token = JWTUtil.genJwt(claims);
        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.fromName(userDO.getIdentity()));
        return userLoginDTO;
    }

    /**
     * 校验是否满⾜注册要求
     *
     * @param request
     */
    private void checkRegisterInfo(UserRegisterParam request) {
        if (null == request) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.REGISTER_INFO_IS_EMPTY);
        }
        // 邮箱格式校验
        if (!RegexUtil.checkMail(request.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }
        // ⼿机号格式校验
        if (!RegexUtil.checkMobile(request.getPhoneNumber())) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        // 检查⾝份信息
        if (null == UserIdentityEnum.fromName(request.getIdentity())) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }
        // 管理员必须设置密码
        if (request.getIdentity().equals(UserIdentityEnum.ADMIN.name())
                && !StringUtils.hasText(request.getPassword())) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }
        // 密码格式校验，最少6位
        if (StringUtils.hasText(request.getPassword())
                && !RegexUtil.checkPassword(request.getPassword())) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.PASSWORD_FORMAT_ERROR);
        }
        // 检查邮箱是否被使⽤
        if (checkMailUsed(request.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }
        // 检查⼿机号是否被使⽤
        if (checkPhoneUsed(request.getPhoneNumber())) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_USED);
        }
    }
    /**
     * 检查⼿机号是否被使⽤
     *
     * @param phoneNumber
     * @return
     */
    private boolean checkPhoneUsed(String phoneNumber) {
        if (!StringUtils.hasText(phoneNumber)) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.PHONE_IS_EMPTY);
        }
        int countUser = userMapper.countByPhoneNumber(new
                Encrypt(phoneNumber));
        return countUser > 0;
    }

    /**
     * 检测邮箱是否被使⽤
     *
     * @param mail
     * @return
     */

    private boolean checkMailUsed(String mail) {
        if (!StringUtils.hasText(mail)) {
            throw new
                    ServiceException(ServiceErrorCodeConstants.MAIL_IS_EMPTY);
        }
        int countUser = userMapper.countByMail(mail);
        return countUser > 0;
    }

}
